<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
/**
 * 2020-02-08
 * 这是从rakuten获取数据判断每天接口新数据
 */
class Rakuten extends Command
{
    protected $signature = 'yw_rakuten';
    protected $description = 'rakuten数据源判断每天新进的卡券数量';

    //定义变量
    private $client;
    private $manager; //mongo驱动
    private $config=[
        'token_url'=>[
            'https://api.rakutenmarketing.com/token?grant_type=password&username=msboperation&password=domenic7adr7&scope=1625937',
            'https://api.rakutenmarketing.com/token?grant_type=password&username=msboperation&password=domenic7adr7&scope=1554277'
        ],
        'total_url'=>'https://api.rakutenmarketing.com/coupon/1.0?resultsperpage=500&pagenumber=',
        'req_param'=>[
            'headers'=>[
                'Authorization'=>'Basic ZklSZ2U2dW1KQ19aYnlPM1NKRjVrSlg4OThnYTowR2g3VXYyNDVyWHd2clY3YmVVb1hrS1R5VUFh',
                'Content-Type'=>'application/x-www-form-urlencoded'
            ]
        ]
    ];
    
    public function __construct()
    {
        parent::__construct();
        $this->client=new Client();
        $this->manager = new \MongoDB\Driver\Manager("mongodb://localhost:27017");
    }
    public function handle(){
        $this->info('*********************program start***********************');
        /**获取token */
        $tokens=$this->getToken();
        if(!$tokens){
            $this->error('Running:'.'获取token失败'.time());
            return;
        }

        /**获取总页数 */
        $page_count=$this->getPageCount($tokens);
        if(!$page_count){
            $this->error('Running:'.'获取页面数量失败'.time());
            return;
        }

        /**获取mongo中已经存在的url */
        $filters=$this->getFilterFromMongoDb();

        $this->saveData($tokens[0],$filters,$page_count[0]);
        $this->saveData($tokens[1],$filters,$page_count[1]);

        /**脚本执行纪律 */
        $log_bulk=new \MongoDB\Driver\BulkWrite;
        $log_bulk->insert(['cj_log'=>'[success]:'.date('Y-m-d H:i:s')]);
        $this->manager->executeBulkWrite('local.yw_log',$log_bulk);
        /** 脚本执行纪律*/
        $this->info('*********************program stop***********************');
    }

    /**
     * 获取token
     * @param null
     * @return array
     */
    private function getToken(){
        $promises=[
            'token1'=>$this->client->requestAsync('POST',$this->config['token_url'][0],$this->config['req_param']),
            'token2'=>$this->client->requestAsync('POST',$this->config['token_url'][1],$this->config['req_param'])
        ];
        $res_token = Promise\unwrap($promises);

        $token_array=[]; //存储获取到的token
        $token_array[]=json_decode($res_token['token1']->getBody()->read(100000000),true)['access_token'];
        $token_array[]=json_decode($res_token['token2']->getBody()->read(100000000),true)['access_token'];
        
        return $token_array;
    }

    /**
     * 获取总页数
     * @param (array)token
     * @return (array)count
     */
    private function getPageCount($token_array){
        $promises2=[
            'total1'=>$this->client->requestAsync('GET',$this->config['total_url'].'1',['headers'=>['Authorization'=>'Bearer '.$token_array[0]],'verify' => false]),
            'total2'=>$this->client->requestAsync('GET',$this->config['total_url'].'1',['headers'=>['Authorization'=>'Bearer '.$token_array[1]],'verify' => false]),
        ];
        $res_total = Promise\unwrap($promises2);

        $page_count=[];
        $page_count[0]=(int)simplexml_load_string($res_total['total1']->getBody()->read(100000000))->TotalPages;
        $page_count[1]=(int)simplexml_load_string($res_total['total2']->getBody()->read(100000000))->TotalPages;
        
        $this->line('Running:'.'获取总页数成功'.time());
        return $page_count;
    }

    /**
     * 获取过滤字段
     * @param null
     * @return (array)urls
     */
    private function getFilterFromMongoDb(){
       //查库参数
       $filter = [];
       $options = [
           'projection' => [
                'filters' => 1,
               '_id'=>0
           ]
       ];

       // 查询数据库中数据
       $query = new \MongoDB\Driver\Query($filter, $options);
       $cursor = $this->manager->executeQuery('local.yw_rakuten', $query);
       
       $urls=[];
       foreach ($cursor as $key => $value) {
           $value=(array)$value;
           $urls[]=$value['filters'];
       }
       $this->line('Running:'.'获取总mongo中的去重数据成功'.time());
       return $urls;
    }

    /**获取并保存数据
     * @param (array)urls
     * @return
     */
    private function saveData($token,$filters,$pagecount){
        //循环抓取页面数据
        for ($i=1; $i <=$pagecount ; $i++) { 
            $tosave_data=$this->getData($token,$this->config['total_url'].$i);
            if(!$tosave_data){
                $this->error('Running:存在抓取异常的接口'.$this->config['total_url'].$i); 
                continue;
            }
            //数据进行集中处理
            $tosave_xml_data=simplexml_load_string($tosave_data);
            $coupons=$tosave_xml_data->link;
            
            //对接口中获取的coupon数据进行
            $to_save_coupons=[];
            foreach ($coupons as $key => $value) {
                $value=json_decode(json_encode($value),true); //转换成json数据
                if(!in_array(md5($value['advertisername'].$value['offerdescription']),$filters)){
                    if(is_array($value['categories']['category'])){
                        $value['category_major']=implode('+',$value['categories']['category']);
                    }else{
                        $value['category_major']=$value['categories']['category'];
                    }
                    $value['filters']=md5($value['advertisername'].$value['offerdescription']);
                    $value['create_time']=date('Y-m-d');
                    $value['crawlDateTime']=date("Y-m-d H:i:s");
                    $to_save_coupons[]=$value;
                }
            }
            //将数据保存到mongodb中
            if($to_save_coupons){
                $bulk = new \MongoDB\Driver\BulkWrite;

                foreach ($to_save_coupons as $key => $value) {
                    $bulk->insert($value); 
                }
                $result=$this->manager->executeBulkWrite('local.yw_rakuten', $bulk);
                $this->line('save new data');
            }else{
                $this->line('same data is out');
            }
        }
    }
    /**
     * 获取数据
     * @param (string)$url,(string $token)
     * return $data
     */
    private function getData($token,$url){
        $res_response=''; //存储抓取到数据
        $response=$this->client->request('GET',$url,['headers'=>['Authorization'=>'Bearer '.$token],'http_errors' => false]);
        $res_response=$response->getBody()->read(100000000);
        
        //抓取结果存在错误则进行二次抓取
        if(strstr($res_response,'fault')){
            $this->error('Running:接口返回数据错误60s后会尝试二次抓取');
            sleep(60);
            $response=$this->client->request('GET',$url,['headers'=>['Authorization'=>'Bearer '.$token],'http_errors' => false]);
            $res_response=$response->getBody()->read(100000000);
            if(strstr($res_response,'fault')){
                return '';
            }
        }
        return $res_response;
    }

}